#!/usr/bin/env python
import argparse
import binascii
import sys
import socket
import random
import struct
import argparse
import hashlib
import datetime
from threading import Thread

from scapy.all import sendp, send, get_if_list, get_if_hwaddr, hexdump
from scapy.all import Packet
from scapy.all import Ether, IP, UDP, TCP
from scapy.all import *
from NDN_header_Interest import NDNInterest
from NDN_header_Data_v import NDNData

TYPE_NDN = 0x8624
ifname = "h2-eth0"


def get_if(ifname):
    ifs = get_if_list()
    iface = None  # "h1-eth0"
    for i in get_if_list():
        if ifname in i:
            iface = i
            break
    if not iface:
        print("Cannot find " + ifname + " interface")
        exit(1)
    return iface


def sendInterest(args):
    pkt_type = 0

    # split name into 4 component: beijing0/bjtu0000/yulei000/index.ht
    ndn_name = "beijing0/bjtu0000/yulei000/index.ht"
    # ndn_name = str(args.name)
    components = ndn_name.split('/', 4)
    # components_hex = [0x0, 0x0, 0x0, 0x0]
    components_hex = [0, 0, 0, 0]
    # print(components)
    # print(components[1])
    # print(binascii.b2a_hex(components[1]))
    for i in range(0, 3 + 1):
        # components_hex[i] = binascii.b2a (components[i])
        components_hex[i] = int(binascii.b2a_hex(components[i]), 16)
    # print (components_hex[0])

    # others
    iface = get_if(args.i)
    if args.with_file is not None:
        pkt_type = 1
    print (pkt_type)

    # interest
    str_pkt_type = 'interest'
    # bind_layers(Ether, NDNInterest, type=TYPE_NDN)
    print("sending {} on interface {}".format(str_pkt_type, iface))
    pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff', type=0x8624)
    # pkt = pkt / IP(dst=addr) / TCP(dport=1234, sport=random.randint(49152, 65535)) / args.message
    pkt = pkt / NDNInterest(Component1=components_hex[0], Component2=components_hex[1],
                            Component3=components_hex[2])

    pkt.show2()
    #    hexdump(pkt)
    #    print "len(pkt) = ", len(pkt)
    current_time = datetime.now()
    print("current_time:    " + str(current_time))
    sendp(pkt, count=1, iface=iface, verbose=False)


def handle_pkt(pkt):
    iface = ifname
    print("got a packet")
    print(type(pkt[Ether].dst))
    if (pkt[Ether].type == 0x8624 and pkt[Ether].dst == "ff:ff:ff:ff:ff:ff"):
        print("got a NDN packet")
        if NDNInterest in pkt and pkt[NDNData].TLV_0_Type == 6:
            print("got a data")
            # --- check Signature !!!
            name_long1 = pkt.Component1
            name_long2 = pkt.Component2
            name_long3 = pkt.Component3
            # name_long4 = pkt[NDNInterest].Component4
            s = hashlib.sha256('')
            s.update(binascii.a2b_hex(hex(name_long1)[2:-1]))
            s.update(binascii.a2b_hex(hex(name_long2)[2:-1]))
            s.update(binascii.a2b_hex(hex(name_long3)[2:-1]))
            # s.update(binascii.a2b_hex(hex(name_long4)[2:-1]))
            s.update(pkt.Content)
            # print(s)
            signature_value = long(s.hexdigest(), 16)
            # --- check Signature !!!
            if pkt[NDNData].Signature_Value == 0:
                print('!!! Signature failure !!!')
            else:
                pkt.show2()

            # sys.stdout.flush()


def sniffpkt():
    bind_layers(Ether, NDNData, type=TYPE_NDN)
    ifaces = list(filter(lambda i: ifname in i, os.listdir(
        '/sys/class/net/')))
    iface = ifaces[0]
    print("sniffing on %s" % iface)
    sys.stdout.flush()
    sniff(iface=iface,
          prn=lambda x: handle_pkt(x))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--i', type=str, help="The interface.")
    parser.add_argument('--name', type=str, help="The name of the interest or data package.")  # 4 components only
    parser.add_argument('--with_file', type=str, help="Set this argument to be a data package")
    args = parser.parse_args()
    # t1 = Thread(target=sendInterest(args))
    t2 = Thread(target=sniffpkt())
    # t1.start()
    t2.start()


if __name__ == '__main__':
    main()
# example
# testApp
# randomData
# %FD%00%00%01%7D%80i%A6%D4
# Hello, world!
# sudo python sendndn.py --i enp27s0 --name beijing0/bjtu0000/yulei000/index.ht --with_file 3
